/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __X_WARN_H__
#define __X_WARN_H__

/* includes (standard library, system) ---------------------------------------*/
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <kconfig.h>
#include <k_critical.h>
#include <k_errno.h>

#include <x_compiler.h>

#ifdef CONFIG_KCONFIG
#include <kprintf.h>
#endif

#include <a_trace.h>

/* includes (local) ----------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* defines -------------------------------------------------------------------*/
/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/

/**
 * WARN - print a warning message
 *
 * usage: WARN (format, args), arguments is the same as kprintf
 */
#ifdef CONFIG_KCONFIG
#define WARN(...)                                                                                  \
    do {                                                                                           \
        if (!in_critical()) {                                                                      \
            uint32_t err = errno;                                                                  \
                                                                                                   \
            kprintf("\nWARNING, " __VA_ARGS__);                                                    \
            kprintf("\n@ (file : %s, line : %d)", __FILE__, __LINE__);                             \
            call_trace();                                                                          \
                                                                                                   \
            errno = err;                                                                           \
        }                                                                                          \
    } while (0)
#else
#define WARN(...)                                                                                  \
    do {                                                                                           \
        if (!in_critical()) {                                                                      \
            uint32_t err = errno;                                                                  \
            call_trace();                                                                          \
                                                                                                   \
            errno = err;                                                                           \
        }                                                                                          \
    } while (0)
#endif

/**
 * WARN_ON - executive code and print a warning message when the result is true
 *
 * code:   the code to executive, note, it will be executived always regardless
 *         to the macro of CONFIG_DEBUG, if the code is comperation only, compiler
 *         can do correct optimization
 * action: action when the result is true, can be a code block or more than one
 *         sentence without ',' and can be empty (do nothing)
 *
 * examples:
 *
 *     WARN_ON (xxx != 0,
 *              return,                         // action
 *              "xxx is %d", xxx);
 *
 *     WARN_ON (xxx != 0, , "xxx is %d", xxx);  // action is empty
 *
 *     WARN_ON (xxx == 0,
 *              errno = ERR_XXX; return -1,     // action is more than one
 *              "xxx is not supported");
 *
 *     WARN_ON (xxx == 0,
 *              {
 *              errno = ERR_XXX;
 *              return -1;
 *              },
 *              "xxx is not supported");
 */
#define WARN_ON(code, action, ...)                                                                 \
    do {                                                                                           \
        if (unlikely(code)) {                                                                      \
            WARN("\"" __CVTSTR_RAW(code) "\" unexpected!\n" __VA_ARGS__);                          \
            action;                                                                                \
        }                                                                                          \
    } while (0)

/* inlines -------------------------------------------------------------------*/
/* externs -------------------------------------------------------------------*/

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __X_WARN_H__ */
